CloudFormationに対応したEC2の起動テンプレートを試してみた

CloudFormationに対応したEC2の起動テンプレートを試してみた

2017年11月リリース、2018年3月CloudFormationからも利用出来る様になった起動テンプレート(Launch Templates for Amazon EC2 instances)を利用して、 EC2インスタンスと、オートスケール環境の設置を試してみました。
Clock Icon2018.06.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

AWSチームのすずきです。

2017年のre:InventでリリースされたEC2の起動テンプレート(Launch Templates for Amazon EC2 instances)。 EC2インスタンスの初期設定をテンプレートとして管理、再利用することが可能になりました。

【速報】新機能 Launch Templates for Amazon EC2 instancesが公開されました #reinvent

[新機能]Launch Templates for Amazon EC2 instancesを試してみた #reinvent

2018年3月、起動テンプレートのCloudFormationサポートがアナウンスされていました。

今回、CloudFormationを利用して、起動テンプレートによるEC2インスタンスと、オートスケール環境の設置を試す機会がありましたので、紹介させていただきます。

利点

CloudFormationで起動テンプレートを利用する利点について、まず紹介させていただきます。

設定の簡略化

  • VPCサブネット指定のみでEC2インスタンスの起動する事が可能になりました。
  • ライセンスなどの関係でオートスケールの導入が難しいが、負荷分散構成をとるEC2インスタンスを多数設置する場合には有効と思われます。
    Type: AWS::EC2::Instance
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref 'Ec2InstanceLaunchTemplate'
        Version: !GetAtt 'Ec2InstanceLaunchTemplate.LatestVersionNumber'
      SubnetId: !Ref 'VpcEc2Subnet1'

バージョン管理

  • 起動テンプレートはバージョン管理機構を備えます。
  • CloudFormationで作成した起動テンプレートを更新(UpdateStack)すると、起動テンプレートのバージョン番号が一つ繰り上がります。
  • 今回、!GetAtt関数を利用し「LatestVersionNumber」を指定、該当起動テンプレートの最新のバージョンを利用する指定としました。
  • 切り戻しなどの場合、バージョン指定を行う事で、古い起動テンプレートを利用したEC2環境を構築できます。
    Type: AWS::EC2::Instance
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref 'Ec2InstanceLaunchTemplate'
        Version: 1
      SubnetId: !Ref 'VpcEc2Subnet1'
  • CloudFormationで作成した起動テンプレートは、AWSコンソール上で、作成日時、作業者情報、設定内容を確認可能です。

タグ管理

  • EC2インスタンス、およびEBSのタグを一括管理する事が可能になりました。
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        TagSpecifications:
        - ResourceType: instance
          Tags:
          - Key: Env
            Value: !Ref 'Env'
        - ResourceType: volume
          Tags:
          - Key: Env
            Value: !Ref 'Env'
  • EC2起動後に増設したEBSや、AMIからの起動時に「Delete on Termination」(併せて削除)指定を省略して作成したEBSは、EC2の撤去後に取り残され用途不明となる事がありましたが、EBSへの適切なタグ付与を行う事で回避しやすくなります。

EC2起動時にEBSボリュームへのタグの付与が可能に!

  • EBSボリュームに適切なタグを付与する事で、コスト配分タグを有効としたAWSアカウントでは、EBSやスナップショット費用についてもタグによるコスト計算が可能になります。

Amazon Elastic Block Store (Amazon EBS) でスナップショットのコスト配分をサポート

T2無制限オプション

  • 「T2」ファミリーのCPUクレジット枯渇を回避するオプション指定を起動テンプレートで設定する事が可能です。
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        CreditSpecification:
          CpuCredits: unlimited
  • 従来のLaunchConfigを利用したオートスケール環境では、T2無制限オプションの有効化のための「Userdata」設定などが必要。awscliのバージョンや、IAMロールの調整が必要でした。

T2 Unlimited(T2無制限)オプションをオートスケール環境で利用してみた

スポットインスタンス

  • スポット入札価格の省略が可能になりました。
  • スポット価格高騰、強制停止に至る場合の動作として、EBS上のデータ消失を回避する停止やハイバネーションの指定も可能になりました。
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        InstanceMarketOptions:
          SpotOptions:
            SpotInstanceType: one-time
            InstanceInterruptionBehavior: terminate
          MarketType: spot

[新機能] Amazon EC2でハイバネーションが可能になりました #reinvent

  • 従来の起動設定(LaunchConfig)でも、スポット価格明示することでスポットインスタンスの利用は可能でしたが、インスタンスファミリーの変更などがあった場合、高額すぎる入札や、廉価すぎる入札により、意図しない状態が発生する事がありました。
    Type: AWS::EC2::LaunchTemplate
    Properties:
      SpotPrice: 0.1

ストレージ設定

LinuxAMI

    Type: AWS::EC2::LaunchTemplate
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 8
            VolumeType: gp2
            DeleteOnTermination: true
        - DeviceName: /dev/xvdf
          Ebs:
            VolumeSize: 1
            VolumeType: gp2
            DeleteOnTermination: true

WindowsAMI

    Type: AWS::EC2::LaunchTemplate
    Properties:
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 30
            VolumeType: gp2
            DeleteOnTermination: true
        - DeviceName: /dev/xvdf
          Ebs:
            VolumeSize: 1
            VolumeType: gp2
            DeleteOnTermination: true

ネットワーク設定

  • 今回オートスケール環境での利用を優先したため設定を省略しましたが、NetworkInterface プロパティタイプによるネットワーク設定は可能です。

  • Amazon EC2 LaunchTemplate NetworkInterface

  • まとめ

    起動テンプレート(Launch Templates)の利用により、 AWSのアップデートで追加された多くのEC2の機能を活用し、より効率的な管理、利用が出来るようになりました。

    特に、初期設定のみCloudFormationを利用、 リリース後のEC2インスタンスの更新、管理についてはAWSコンソールやCLIの利用が想定される環境では、 起動テンプレートの利用は大きな効果があると思われます。

    また、起動テンプレートはスポットフリートや、AWS Auto Scalingとの連係にも利用することが可能です。 こちらは別の機会に改めて紹介させて頂きたいと思います。

    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-automatic-scaling.html

    テンプレート

    • 今回紹介した環境のCloudFormationテンプレート(YAML)です。
    • オートスケールと非オートスケールで、同一設定の2台のEC2インスタンスが起動します。
    • AMIはAWS東京リージョンのAmazon Linux 2 LTS Candidate 2 をデフォルトのパラメータに反映しています
    • 既存のVPC(デフォルトVPC)とサブネット、SSH接続情報をパラメータで指定します
    • Userdataの動作確認の為、awslogs(CloudwatchLogsAgent)の設定を実施しています
    AWSTemplateFormatVersion: '2010-09-09'
    Description: ec2-LaunchTemplate-instance
    Parameters:
      Env:
        Description: Choose the environment to create
        Type: String
        Default: development
        AllowedValues:
        - development
        - staging
        - production
      VpcId:
        Description: VPC ID
        Type: AWS::EC2::VPC::Id
      VpcSubnetCidr:
        Description: VPC subnet CIDR
        Type: String
        Default: 172.31.0.0/16
      StaticIPforSSH:
        Description: Static IP for SSH access
        Type: String
        Default: 127.0.0.1/32
      VpcEc2Subnet1:
        Description: EC2 subnet 1(AZ-a)
        Type: AWS::EC2::Subnet::Id
      VpcEc2Subnet2:
        Description: EC2 subnet 2(AZ-c)
        Type: AWS::EC2::Subnet::Id
      Ec2ImageId:
        Description: AMI ID
        Type: String
        Default: ami-2724cf58
      Ec2InstanceType:
        Description: EC2 InstanceType
        Type: String
        Default: t2.micro
      Ec2InstanceKeyName:
        Description: EC2 SSH KEY
        Type: AWS::EC2::KeyPair::KeyName
        Default: SSHKey
      Ec2InstanceTagName:
        Description: EC2 Tag Name
        Type: String
        Default: test-lt-ec2-20180605
      Ec2AutoscaleMinSize:
        Description: AutoScalingGroup MinSize
        Type: String
        Default: '1'
      Ec2AutoscaleMaxSize:
        Description: AutoScalingGroup MaxSize
        Type: String
        Default: '1'
      Ec2AutoscaleDesiredCapacity:
        Description: AutoScalingGroup DesiredCapacity
        Type: String
        Default: '1'
    Resources:
      Ec2InstanceLaunchTemplate:
        Type: AWS::EC2::LaunchTemplate
        Properties:
          LaunchTemplateData:
            SecurityGroupIds:
            - !Ref 'Ec2SecurityGroup'
            - !Ref 'Ec2SecurityGroupSSH'
            TagSpecifications:
            - ResourceType: instance
              Tags:
              - Key: Env
                Value: !Ref 'Env'
            - ResourceType: volume
              Tags:
              - Key: Env
                Value: !Ref 'Env'
            - ResourceType: instance
              Tags:
              - Key: Name
                Value: !Ref 'AWS::StackName'
            UserData:
              Fn::Base64: |
                #!/bin/bash -xe
                date > /tmp/run.log
                yum update -y
                yum install jq awslogs -y
                chkconfig awslogs on
                service awslogs start
                if [ ! -f /swapfile ]; then dd if=/dev/zero of=/swapfile bs=1M count=128; chmod 600 /swapfile; mkswap /swapfile; swapon /swapfile; echo "/swapfile  swap  swap  defaults  0  0" >> /etc/fstab; fi
            InstanceInitiatedShutdownBehavior: terminate
            IamInstanceProfile:
              Arn: !GetAtt 'Ec2IAMProfile.Arn'
            KeyName: !Ref 'Ec2InstanceKeyName'
            ImageId: !Ref 'Ec2ImageId'
            Monitoring:
              Enabled: false
            CreditSpecification:
              CpuCredits: standard
            InstanceType: !Ref 'Ec2InstanceType'
            InstanceMarketOptions:
              SpotOptions:
                SpotInstanceType: one-time
                InstanceInterruptionBehavior: terminate
              MarketType: spot
            BlockDeviceMappings:
            - DeviceName: /dev/xvda
              Ebs:
                VolumeSize: 8
                VolumeType: gp2
                DeleteOnTermination: true
            - DeviceName: /dev/xvdf
              Ebs:
                VolumeSize: 1
                VolumeType: gp2
                DeleteOnTermination: true
    
      Ec2Instance:
        Type: AWS::EC2::Instance
        Properties:
          LaunchTemplate:
            LaunchTemplateId: !Ref 'Ec2InstanceLaunchTemplate'
            Version: !GetAtt 'Ec2InstanceLaunchTemplate.LatestVersionNumber'
          SubnetId: !Ref 'VpcEc2Subnet1'
      Ec2InstanceAutoScalingGroup:
        Type: AWS::AutoScaling::AutoScalingGroup
        Properties:
          VPCZoneIdentifier:
          - !Ref 'VpcEc2Subnet1'
          - !Ref 'VpcEc2Subnet2'
          LaunchTemplate:
            LaunchTemplateId: !Ref 'Ec2InstanceLaunchTemplate'
            Version: !GetAtt 'Ec2InstanceLaunchTemplate.LatestVersionNumber'
          MinSize: !Ref 'Ec2AutoscaleMinSize'
          MaxSize: !Ref 'Ec2AutoscaleMaxSize'
          DesiredCapacity: !Ref 'Ec2AutoscaleDesiredCapacity'
      Ec2SecurityGroup:
        Type: AWS::EC2::SecurityGroup
        Properties:
          VpcId: !Ref 'VpcId'
          GroupDescription: allow ICMP via same VPC
          SecurityGroupIngress:
          - IpProtocol: icmp
            FromPort: -1
            ToPort: -1
            CidrIp: !Ref 'VpcSubnetCidr'
      Ec2SecurityGroupSSH:
        Type: AWS::EC2::SecurityGroup
        Properties:
          VpcId: !Ref 'VpcId'
          GroupDescription: allow SSH via static IP
          SecurityGroupIngress:
          - IpProtocol: tcp
            FromPort: 22
            ToPort: 22
            CidrIp: !Ref 'StaticIPforSSH'
      Ec2IAMRole:
        Type: AWS::IAM::Role
        Properties:
          AssumeRolePolicyDocument:
            Statement:
            - Effect: Allow
              Principal:
                Service:
                - ec2.amazonaws.com
              Action:
              - sts:AssumeRole
          ManagedPolicyArns:
          - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
          Path: /
          Policies: !Ref 'AWS::NoValue'
          RoleName: !Ref 'AWS::NoValue'
      Ec2RolePolicies:
        Type: AWS::IAM::Policy
        Properties:
          PolicyName: Ec2RolePolicies
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
            - Effect: Allow
              Action:
              - s3:List*
              Resource:
              - '*'
            - Effect: Allow
              Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
              - logs:DescribeLogStreams
              Resource:
              - arn:aws:logs:*:*:*
          Roles:
          - !Ref 'Ec2IAMRole'
      Ec2IAMProfile:
        Type: AWS::IAM::InstanceProfile
        DependsOn: Ec2IAMRole
        Properties:
          Path: /
          Roles:
          - !Ref 'Ec2IAMRole'
    
    

    Share this article

    facebook logohatena logotwitter logo

    © Classmethod, Inc. All rights reserved.